#
# peerscape.daemon.daemon
#
# Copyright 2006-2009 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Ken Rimey <rimey@hiit.fi>
#

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from __future__ import with_statement

import time
import logging
from threading import Thread

from peerscape import DB

def init_db(path):
    db = DB(path)
    try:
        logging.info('-' * 50)
        db.log_version()
        logging.info('Sqlite wrapper: %s', db.sqlite_wrapper)
        logging.info('My node ID: %s', db.my_id)

        # Wonder Wall App:
        db.subscribe('93f5f1c52c5f43a29102cf0b06197d863b85518d')

        # XXX Temporary:
        try:
            iid = db.get_my_iid()
            db.add_signing_policy(iid, '!', '/info/modified')
            db.add_signing_policy(iid, '!', '/public/event.json')
            db.add_signing_policy(iid, '!', '/restricted/event.json')
            db.add_signing_policy(iid, '*', '/inbox/!')
        except LookupError:
            pass
    finally:
        db.close()

class Daemon(object):
    def __init__(self, path,
                 sync=True, crawl=True, escrow=True, register=True,
                 http=False, cherrypy=True,
                 ftp=False, monitor=False,
                 sync_host='', sync_port=35800,
                 http_host='localhost', http_port=35880,
                 ftp_host='localhost', ftp_port=2121):
        self.path = path
        self.enable_sync = sync
        self.enable_crawl = crawl
        self.enable_escrow = escrow
        self.enable_registration = register
        self.enable_http = http
        self.cherrypy = cherrypy
        self.enable_ftp = ftp
        self.enable_monitor = monitor

        self.sync_host = sync_host
        self.sync_port = sync_port

        self.http_host = http_host
        self.http_port = http_port

        self.ftp_host = ftp_host
        self.ftp_port = ftp_port

    def loop(self):
        self.init()
        self.start()

        try:
            if self.enable_monitor:
                self.monitor()
            else:
                sleep_forever()
        except KeyboardInterrupt:
            pass

        self.stop()
        print 'Exiting...'

    def init(self):
        init_db(self.path)

    def start(self):
        if self.enable_http:
            self.start_http()
            time.sleep(0.2) # Give the HTTP server a little time to start up.

        if self.enable_ftp:
            self.start_ftp()

        if self.enable_sync:
            self.start_sync()

        if self.enable_crawl:
            self.start_crawl()

        if self.enable_escrow:
            self.start_escrow()

        if self.enable_registration:
            self.start_registration()

    def stop(self):
        if self.enable_sync:
            self.sync_daemon.close()
            self.sync_thread.join()

    def start_sync(self):
        from peerscape.sync.sync_daemon import SyncDaemon

        self.sync_daemon = SyncDaemon(path=self.path,
                                      host=self.sync_host,
                                      port=self.sync_port)
        self.sync_thread = Thread(target=self.sync_daemon.loop,
                                  name='sync-thread')
        self.sync_thread.setDaemon(True)
        self.sync_thread.start()

    def start_crawl(self):
        from peerscape.replication.crawl import Crawler

        self.crawler = Crawler(path=self.path)
        self.crawler_thread = Thread(target=self.crawler.loop,
                                     name='crawler-thread')
        self.crawler_thread.setDaemon(True)
        self.crawler_thread.start()

    def start_escrow(self):
        from peerscape.db.escrow import EscrowAgent

        self.escrow_agent = EscrowAgent(path=self.path)
        self.escrow_thread = Thread(target=self.escrow_agent.loop,
                                    name='escrow-thread')
        self.escrow_thread.setDaemon(True)
        self.escrow_thread.start()

    def start_registration(self):
        from peerscape.daemon.register import RegistrationAgent

        self.registration_agent = RegistrationAgent(path=self.path)
        self.registration_thread = Thread(target=self.registration_agent.loop,
                                          name='registration-thread')
        self.registration_thread.setDaemon(True)
        self.registration_thread.start()

    def start_http(self):
        from peerscape.http.wsgiserver import serve

        args = self.path, self.http_host, self.http_port, self.cherrypy
        self.http_thread = Thread(target=serve, args=args,
                                  name='http-thread')
        self.http_thread.setDaemon(True)
        self.http_thread.start()

    def start_ftp(self):
        from peerscape.ftp.server import serve

        args = self.path, self.ftp_host, self.ftp_port
        self.ftp_thread = Thread(target=serve, args=args,
                                  name='ftp-thread')
        self.ftp_thread.setDaemon(True)
        self.ftp_thread.start()

    def monitor(self):
        from peerscape.daemon.monitor import Monitor

        Monitor(path=self.path, daemon=self).loop()

def sleep_forever():
    while True:
        time.sleep(30)

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    daemon = Daemon()
    daemon.loop()
